package cn.itcast.wanxinp2p.consumer.service.impl;

import cn.itcast.wanxinp2p.common.domain.CodePrefixCode;
import cn.itcast.wanxinp2p.common.domain.CommonErrorCode;
import cn.itcast.wanxinp2p.common.domain.RestResponse;
import cn.itcast.wanxinp2p.common.exception.TccTryException;
import cn.itcast.wanxinp2p.common.util.CodeNoUtil;
import cn.itcast.wanxinp2p.consumer.agent.fegin.AccountApiAgent;
import cn.itcast.wanxinp2p.consumer.common.ConsumerErrorCode;
import cn.itcast.wanxinp2p.consumer.entity.pojo.Consumer;
import cn.itcast.wanxinp2p.consumer.mapper.ConsumerMapper;
import cn.itcast.wanxinp2p.consumer.mapper.TccMapper;
import cn.itcast.wanxinp2p.consumer.service.ConsumerService;
import cn.itcast.wanxinp2p.common.exception.BusinessException;
import cn.itcast.wanxinp2p.dto.account.AccountDTO;
import cn.itcast.wanxinp2p.dto.account.AccountRegisterDTO;
import cn.itcast.wanxinp2p.dto.comsumer.ConsumerRegisterDTO;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.dromara.hmily.core.concurrent.threadlocal.HmilyTransactionContextLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service
@Slf4j
public class ConsumerServiceImpl implements ConsumerService {

    /**
     * 注入ConsumerMapper层
     */
    @Autowired
    private ConsumerMapper consumerMapper;

    /**
     * 引入fegin远程调用
     */
    @Autowired
    private AccountApiAgent accountApiAgent;

    /**
     * 引入TCC校验
     */
    @Autowired
    private TccMapper tccMapper;


    @Override
    public Integer checkMobile(String mobile) {
        //根据手机号查询用户，存在返回1 不存在返回0
        return null;
    }

    /**
     * 用户中心服务实现保存功能
     *  try幂等校验
     *  try悬挂处理
     *  检查用户是否存在
     *  新增用户
     * @param consumerRegisterDTO 前端用户注册信息
     */
    @Override
    @Hmily(cancelMethod = "cancelRegister",confirmMethod = "confirmRegister")
    public void register(ConsumerRegisterDTO consumerRegisterDTO) {
        System.out.println("----------开启事务 执行try操作----------");
        /**
         * TCC校验
         */
        //获取全局事务ID
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("consumer try 开始执行...xid:{}",transId);
        //判断有没有这个事务
        if (tccMapper.isExistTry(transId) > 0) {
            log.info("consumer try 已经执行，无需重复执行,xid:{}",transId);
            return;
        }
        //try悬挂处理，如果cancel、confirm有一个已经执行了，try不再执行
        if (tccMapper.isExistCancel(transId) > 0 || tccMapper.isExistCancel(transId)>0) {
            throw new TccTryException("出现悬挂现象，transId: " + transId);
        }

        /**
         * 执行新增用户业务
         */
        //1、检测是否已注册，如果已经注册，则抛出 ConsumerErrorCode.E_140107 异常
        String mobile = consumerRegisterDTO.getMobile();
        Consumer flag = consumerMapper.selectByMobile(mobile);
        if (!StringUtils.isEmpty(flag)){
            throw new BusinessException(ConsumerErrorCode.E_140107);
        }
        //2、如果用户没有注册，则保存该用户数据 到 consumer 表中
        Consumer consumer = new Consumer();
        BeanUtils.copyProperties(consumerRegisterDTO,consumer);
        //配置系统生成用户名
        consumer.setUsername(CodeNoUtil.getNo(CodePrefixCode.CODE_NO_PREFIX));
        //配置用户编码
        consumer.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));
        //是否绑定银行卡默认0
        consumer.setIsBindCard(0);

        consumerMapper.insertByConsumer(consumer);
        //插入try执行记录,用于幂等判断
        tccMapper.addTry(transId);

        //3、并通过Feign远程调用 统一账号服务 实现 账号的保存
        AccountRegisterDTO accountRegisterDTO = new AccountRegisterDTO();
        BeanUtils.copyProperties(consumerRegisterDTO,accountRegisterDTO);
        RestResponse<AccountDTO> response =
                accountApiAgent.register(accountRegisterDTO);
        //4、判断结果
        if (response.getCode()!= CommonErrorCode.SUCCESS.getCode()){
            throw new BusinessException(ConsumerErrorCode.E_140106);
        }
        log.info("consumer try end 结束执行...xid:{}",transId);
    }


    /**
     * 提交事务方法
     * @param consumerRegisterDTO 前端用户注册信息
     */
    @Override
    public void confirmRegister(ConsumerRegisterDTO consumerRegisterDTO) {
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("执行提交操作 consumer  begin 开始执行...xid:{}",transId);
    }


    /**
     * cancel方法
     * cancel幂等校验
     * cancel空回滚处理
     * 删除用户
     */
    @Override
    public void cancelRegister(ConsumerRegisterDTO consumerRegisterDTO) {
        log.info("执行回滚操作");
        //获取全局事务id
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        //cancel幂等校验
        if(tccMapper.isExistCancel(transId)>0){
            log.info("consumer  cancel 已经执行，无需重复执行,xid:{}",transId);
            return ;
        }
        //cancel空回滚处理，如果try没有执行，cancel不允许执行
        if(tccMapper.isExistTry(transId)<=0){
            log.info("consumer  空回滚处理，try没有执行，不允许cancel执行,xid:{}",transId);
            return ;
        }
        //执行删除操作
        Consumer consumer = new Consumer();
        BeanUtils.copyProperties(consumerRegisterDTO,consumer);
        consumerMapper.deleteByConsumer(consumer);
        //插入一条cancel的执行记录
        tccMapper.addCancel(transId);
        log.info("consumer cancel end 结束执行...xid:{}",transId);

    }


}
